#include "QueryEvaluator.h"


/** Class Constructor
   * 
   * @Intialises result vectors and validation tables
   */
QueryEvaluator::QueryEvaluator()
{


	queryPreprocessor.createEntityTable();
	queryPreprocessor.createEntityRelTable();

	struct resultTypes tempResultStruct;
	vector<vector<int>> tempResult;
	tempResultStruct.resultEntity = tempResult;
	for(int i =0;i<11;i++)
	{
		result.resultVector.push_back(tempResultStruct);
		result.noOfRows++;
		independentResult.resultVector.push_back(tempResultStruct);
	}


};

/** Execute Query.
   * 
   * @param list of strings which will contain query result
   * @return the result of the query in the list
   */
int QueryEvaluator::executeQuery(list<string>& resultVector)
{
	QueryOptimizer queryOptimize;
	deleteAllRows(result);
	deleteAllRows(independentResult);
	withMapping.clear();
	bool allIndependent = true;
	result.noOfRows = 0;
	clearWithMapping();
	vector<int> tempResultVector1;
	vector<int> tempResultVector2;
	vector<Result> withResult;
	int tempCount = 0;
	int resultIndex =  0;
	int relationshipIndex = 0;
	vector<int> argumentsIndex;
	bool resultExists = true;
	
	int resultValue = 0;
	int j =0 ;
	unsigned int i =0;
	bool withAns = false;
	bool patternAns = false;
	if(with.size()!=0)
	{
		while(i<with.size())
		{

			
			if(with[i].withType==_VALUE)
			{
				
				int withVarExists = checkWithMapping(with[i].arguments[0].argument,with[i].arguments[0].argumentInd,with[i].arguments[1].argument);
				if(withVarExists==-1)
				{
				if(result.selectedType[0]==_BOOLEAN)
					{
					resultVector.push_back("false");
					
					}
					return 1;
				}
					
				if(withVarExists!=2)
				{
				withMapping[with[i].arguments[0].argument].push_back(with[i].arguments[0].argumentInd);
				withMapping[with[i].arguments[0].argument].push_back(with[i].arguments[1].argument);
				for(unsigned int l=0;l<result.selectedType.size();l++)
				{
				if((with[i].arguments[0].argument==result.selectedType[l]) &&( with[i].arguments[0].argumentInd==result.resultIndex[l]))
				{
					withAns = true;
				    tempCount++;	
				}
				}
				tempResultVector1.push_back(with[i].arguments[1].argument);
				intersectResult(result,tempResultVector1,tempResultVector2,with[i].arguments[0],with[i].arguments[1],0);
				
				}
				
			}
			else
			{
				resultValue = query.getWith(tempResultVector1,tempResultVector2,with[i].arguments[0],with[i].arguments[1]);
				if(resultValue==-1)
				{
					if(result.selectedType[0]==_BOOLEAN)
					{
					resultVector.push_back("false");
					
					}
					return 1;
				}
				else
				{
					for(unsigned int l=0;l<result.selectedType.size();l++)
				{
				if(((with[i].arguments[0].argument==result.selectedType[l]) &&( with[i].arguments[0].argumentInd==result.resultIndex[l]))||((with[i].arguments[1].argument==result.selectedType[l]) &&( with[i].arguments[1].argumentInd==result.resultIndex[l])))
				{
					withAns = true;	
				}
				}
				if((with[i].arguments[0].argument==with[i].arguments[1].argument)&&(with[i].arguments[0].argumentInd==with[i].arguments[1].argumentInd))
				 intersectResult(result,tempResultVector1,tempResultVector2,with[i].arguments[0],with[i].arguments[1],0);
				else
					intersectResult(result,tempResultVector1,tempResultVector2,with[i].arguments[0],with[i].arguments[1],1);
				}

			}
			
			tempResultVector1.clear();
			tempResultVector2.clear();

			i++;
		}
	}
	
	tempResultVector1.clear();
	tempResultVector2.clear();
	unsigned int y = 0;
	if(pattern.size()!=0)
	{
		
		while(y<pattern.size())
		{
			if(with.size()>0)
			{
				int argType1 = getWithMapping(pattern[y].arguments[0].argument,pattern[y].arguments[0].argumentInd,pattern[y].arguments[0].argumentType);
				int argType2 = getWithMapping(pattern[y].arguments[1].argument,pattern[y].arguments[1].argumentInd,pattern[y].arguments[1].argumentType);
				if(argType1>=0)
				{
					pattern[j].arguments[0].argumentType = argType1;
				}
				if(argType2>=0)
				{
					pattern[j].arguments[1].argumentType = argType2;
				}
			}
			int patterRes = query.getPattern(tempResultVector1,tempResultVector2,pattern[y].arguments[0],pattern[y].arguments[1],pattern[y].stringArgument);
			if(patterRes == -1)
			{
				if(result.selectedType[0]==_BOOLEAN)
					{
					resultVector.push_back("false");
					
					}
					return 1;
			}
			if((pattern[y].arguments[1].argumentType==ARGUMENT)&&(pattern[y].arguments[1].argument!=_UNDERSCORE))
				intersectResult(result,tempResultVector1,tempResultVector2,pattern[y].arguments[0],pattern[y].arguments[1],1);
			else
				intersectResult(result,tempResultVector1,tempResultVector2,pattern[y].arguments[0],pattern[y].arguments[1],0);
			for(unsigned int l=0;l<result.selectedType.size();l++)
				{
				if((pattern[y].arguments[0].argument==result.selectedType[l]) &&( pattern[y].arguments[0].argumentInd==result.resultIndex[l]))
				{
					patternAns = true;	
				}
				}
			tempResultVector1.clear();
			tempResultVector2.clear();
			if(result.noOfRows==0)
			{
				if(result.selectedType[0]==_BOOLEAN)
					{
						resultVector.push_back("false");
					}
					return 1;

			}
			y++;
		}
		
	}
	
	tempResultVector1.clear();
	tempResultVector2.clear();
	int depCount = 0;
	if(suchThat.size()!=0)
	{
		vector<int> suchThatMapping;
		queryOptimize.optimizeClause(suchThat,suchThatMapping);
		unsigned int loopSuchThat = 0;
		
		while(loopSuchThat<suchThat.size())
		{
			j = suchThatMapping[loopSuchThat];
			if(suchThat[j].index!=1)
			{
				allIndependent = false;
			}
			relationshipIndex = suchThat[j].relationshipType;
			if(with.size()>0)
			{
				int argType1 = getWithMapping(suchThat[j].arguments[0].argument,suchThat[j].arguments[0].argumentInd,suchThat[j].arguments[0].argumentType);
				int argType2 = getWithMapping(suchThat[j].arguments[1].argument,suchThat[j].arguments[1].argumentInd,suchThat[j].arguments[1].argumentType);
				if(argType1>=0)
				{
					suchThat[j].arguments[0].argumentType = argType1;
				}
				if(argType2>=0)
				{
					suchThat[j].arguments[1].argumentType = argType2;
				}
			}
			if(relationshipIndex==FOLLOWS)
			{
				resultValue = query.getFollow(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==FOLLOWST)
			{
				resultValue = query.getFollowT(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==MODIFIES)
			{
				resultValue = query.getModify(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==USES)
			{
				resultValue = query.getUses(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==PARENT)
			{
				resultValue = query.getParent(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==PARENTT)
			{
				resultValue = query.getParentT(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==CALLS)
			{
				resultValue = query.getCalls(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==CALLST)
			{
				resultValue = query.getCallsT(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==NEXT)
			{
				resultValue = query.getNext(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==NEXTT)
			{
				resultValue = query.getNextT(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==AFFECTS)
			{
				resultValue = query.getAffects(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}
			if(relationshipIndex==AFFECTST)
			{
				resultValue = query.getAffectsT(tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1]);
			}

			 if(((suchThat[j].arguments[0].argumentType!=5)&&(suchThat[j].arguments[1].argumentType!=5))||((suchThat[j].arguments[0].argument==_UNDERSCORE)&&(suchThat[j].arguments[1].argument==_UNDERSCORE))||((suchThat[j].arguments[0].argumentType!=5)&&(suchThat[j].arguments[1].argument==_UNDERSCORE))||((suchThat[j].arguments[1].argumentType!=5)&&(suchThat[j].arguments[0].argument==_UNDERSCORE)))
			{
			if(result.selectedType[0]==_BOOLEAN)
			{
				if(resultValue==-1)
				{
				resultExists = false;
				break;
				}
			
			}
			else
			{
			if(resultValue==-1)
				{
				return 1;
				}
			}
			}
			else if(suchThat[j].arguments[0].argumentType!=5||suchThat[j].arguments[0].argument==_UNDERSCORE)
			{
				if(tempResultVector2.size()<=0)
				{
					if(result.selectedType[0]==_BOOLEAN)
					{
						resultExists = false;
						break;
					}
					return 1;
				}
				if(suchThat[j].index==-1)
				{
					
				intersectResult(result,tempResultVector2,tempResultVector1,suchThat[j].arguments[1],suchThat[j].arguments[0],0);
				}
				else
				{
				intersectResult(independentResult,tempResultVector2,tempResultVector1,suchThat[j].arguments[1],suchThat[j].arguments[0],0);
				}
				if((result.noOfRows==0&&suchThat[j].index==-1)||(independentResult.noOfRows==0&&suchThat[j].index==1))
			{
				if(result.selectedType[0]==_BOOLEAN)
					{
						resultExists = false;
						break;
					}
					return 1;

			}
			}
			else if(suchThat[j].arguments[1].argumentType!=5||suchThat[j].arguments[1].argument==_UNDERSCORE||((suchThat[j].arguments[0].argument==suchThat[j].arguments[1].argument)&&(suchThat[j].arguments[0].argumentInd==suchThat[j].arguments[1].argumentInd)))
			{
				if(tempResultVector1.size()<=0)
				{
					if(result.selectedType[0]==_BOOLEAN)
					{
						resultExists = false;
						break;
					}
					return 1;
				}
				if(suchThat[j].index==-1)
				{
			intersectResult(result,tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1],0);
				}
				else
				{
					intersectResult(independentResult,tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1],0);
			
				}
				if((result.noOfRows==0&&suchThat[j].index==-1)||(independentResult.noOfRows==0&&suchThat[j].index==1))
			{
				if(result.selectedType[0]==_BOOLEAN)
					{
						resultExists = false;
						break;
					}
					return 1;

			}
				}
			else
			{
				if((tempResultVector2.size()<=0)||(tempResultVector1.size()<=0))
				{
					if(result.selectedType[0]==_BOOLEAN)
					{
						resultExists = false;
						break;
					}
					return 1;
				}
			if(suchThat[j].index==-1)
			{
				int arg1Nec = checkArgumentNecessity(result,suchThat[j].arguments[0],suchThat);
				int arg2Nec = checkArgumentNecessity(result,suchThat[j].arguments[1],suchThat);
				if(arg1Nec==1)
				{
					if(arg2Nec==1)
					{
					intersectResult(result,tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1],1);
					}
					else
					{
					 std::sort(tempResultVector1.begin(),tempResultVector1.end());
					 tempResultVector1.erase(std::unique(tempResultVector1.begin(),tempResultVector1.end()),tempResultVector1.end());
					intersectResult(result,tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1],0);
					}
				}
				else
				{
					std::sort(tempResultVector2.begin(),tempResultVector2.end());
					 tempResultVector2.erase(std::unique(tempResultVector2.begin(),tempResultVector2.end()),tempResultVector2.end());
					intersectResult(result,tempResultVector2,tempResultVector1,suchThat[j].arguments[1],suchThat[j].arguments[0],0);
			
				}

			}
			else
			{
				intersectResult(independentResult,tempResultVector1,tempResultVector2,suchThat[j].arguments[0],suchThat[j].arguments[1],1);
			}
			if((result.noOfRows==0&&suchThat[j].index==-1)||(independentResult.noOfRows==0&&suchThat[j].index==1))
			{
				if(result.selectedType[0]==_BOOLEAN)
					{
						resultExists = false;
						break;
					}
					return 1;

			}
			}
			
			tempResultVector1.clear();
			tempResultVector2.clear();
			loopSuchThat++;
		}

	}
	
		
	
	if(with.size()==0 && suchThat.size()==0&&pattern.size()==0)
	{
		if(result.selectedType[0]!=_BOOLEAN)
		{
			query.getAll(resultVector,result.selectedType,result.resultAtrributeType);
		}
		else
		{
			resultVector.push_back("true");
			return 1;
		}

	}
	else
	{
		if(result.selectedType[0]==_BOOLEAN)
		{
			if(resultExists)
			{
				resultVector.push_back("true");
			}
			else
			{	
				resultVector.push_back("false");
			}
		}
		else
		{
			if(allIndependent==true&&withAns==false&&patternAns==false)
			{
				
				query.getAll(resultVector,result.selectedType,result.resultAtrributeType);
			}
			else
			{
			getEntityMapping(result,resultVector);
			}
		}
	}
	return 1;

};

/** Validate Query.
   * 
   * @param the query in string format and the query result list.
   * @return validates the query and return a value < 0 if the query is invalid
   */
int QueryEvaluator::validateQuery(string query,list<string> &resultVector)
{


	int validationResult = queryPreprocessor.createQueryTree(query,suchThat,result,with,pattern);
	if(result.selectedType.size()!=0)
	{
	if(result.selectedType[0]==_BOOLEAN&&validationResult<0)
	{
		
		resultVector.push_back("false");
	}
	}
	return validationResult;




	};

/** Get Entity Mapping
   * 
   * @param result structure containing the current result set and result list
   * @return the result of the query in the list
   */
void QueryEvaluator::getEntityMapping(struct Result& tempResult,list<string>& resultVector)
	{
		string tempName;
		string tempStrResult=  "";
	QueryProcessor queryObj;
	vector<int> tempResultVector1;
	vector<int> tempResultVector2;
	Argument tempArgument;
	Argument tempArgument1;
	for(unsigned int p=0;p<tempResult.selectedType.size();p++)
	{
		if(tempResult.resultVector[tempResult.selectedType[p]].resultEntity[tempResult.resultIndex[p]].size()==0)
		{

			query.getAll(tempResultVector1,tempResult.selectedType[p]);
				tempArgument.argument = tempResult.selectedType[p];
			    tempArgument.argumentInd = tempResult.resultIndex[p];
				tempArgument.argumentType = ARGUMENT;
				intersectResult(tempResult,tempResultVector1,tempResultVector2, tempArgument, tempArgument1,0);
				tempResultVector1.clear();
		}
	}
	for(int i =0;i<tempResult.noOfRows;i++)
	{
	for(unsigned int p=0;p<tempResult.selectedType.size();p++)
	{

		if(tempResult.selectedType[p]==_PROCEDURE||tempResult.selectedType[p]==_VARIABLE||tempResult.resultAtrributeType[p]==_PROCNAME)
	{
		
		tempStrResult = tempStrResult + queryObj.getEntityName(tempResult.resultVector[tempResult.selectedType[p]].resultEntity[tempResult.resultIndex[p]][i],tempResult.selectedType[p]);
		if(p!=(tempResult.selectedType.size()-1))
		{
			tempStrResult = tempStrResult + " ";
		}
		}

	
	else
	{
		
			char temp[50];
			sprintf(temp,"%d",tempResult.resultVector[tempResult.selectedType[p]].resultEntity[tempResult.resultIndex[p]][i]);
			tempStrResult = tempStrResult + temp;
			if(p!=(tempResult.selectedType.size()-1))
		{
			tempStrResult = tempStrResult + " ";
		}
			
		}

	
	}
	resultVector.push_back(tempStrResult);
	tempStrResult = "";
	}
	}

/** Clear With Mapping
   * 
   * @Clears the with mapping used for with queries of type value
   */
int QueryEvaluator::clearWithMapping()
{
	vector<int> init;
	init.push_back(-1);
	init.push_back(-1);

	for(int k=0;k<11;k++)
	{
		withMapping.push_back(init);
	}
	return 1;
};

/** Generate Mapping
   * 
   * @param the variable type and a vector of the variable synonyms of that type
   * @Inserts the variables into the entity table
   */
void QueryEvaluator::generateMapping(int variableType,vector<string>& variable)
{

	queryPreprocessor.createMapping(variableType,variable,result,independentResult);

};

/** Check With Mapping
   * 
   * @param The argument, argumentIndex and the value of the argument if it already has one
   * @return Returns 2 if the variable already exists and is of same value, -1 if it of different value
   *		and 1 if it doesnt exist.
   */
int QueryEvaluator::checkWithMapping(int argument,int argumentInd, int argumentResult)
{
	for(unsigned int q=0;q<(withMapping[argument].size()-1);q++)
	{
		if((argumentInd==withMapping[argument][q])&&argumentInd!=-1)
		{
			if(argumentResult==withMapping[argument][q+1])
				return 2;
			else
			{
				return -1;
			}
		}
		q++;
	}

	return 1;
};

/** Get With Mapping
   * 
   * @param The argument, argumentIndex and the type of the argument 
   * @return Returns -1 if the variable doesnt exists ,  the variable value if it does exist.
   */
int QueryEvaluator::getWithMapping(int &arg, int argInd,int argumentType)
{
	int resultType = -1;
	if(argumentType==5)
	{
	if(arg==_STMT||arg==_IF||arg==_WHILE||arg==_CALL||arg==_ASSIGN)
	{
		resultType =INTARGUMENT;
	}
	if(arg==_PROCEDURE)
	{
		resultType = PROCARGUMENT;
	}
	if(arg==_VARIABLE)
	{
		resultType = VARARGUMENT;
	}
	}
	else
	{
		return -1;
	}
	for(unsigned int q=0;q<(withMapping[arg].size()-1);q++)
	{
		if((argInd==withMapping[arg][q])&&argInd!=-1)
		{
			arg = withMapping[arg][q+1];
			return resultType;
		}
		q++;
	}



	return -1;




};

/** Intersect Result
   * 
   * @param The current result set, the results and arguments from the current query.
   * @Intersects the result of the current query with the existing result.
   */
int QueryEvaluator::intersectResult(struct Result& result3, vector<int>& result1, vector<int>& result2, struct Argument& argument1, struct Argument& argument2, int both)
{
	int argumentTempInd = 0;//argument of dependent column
	int argumentTemp = 0;//argumentInd of dependent column


	int empty = checkEmpty(result3);
	//case 1: No result in result set. 
	if(empty==1)
	{
		for(unsigned int i = 0;i<result1.size();i++)
		{
			result3.resultVector[argument1.argument].resultEntity[argument1.argumentInd].push_back(result1[i]);
			
			if(both==1)
			{
				result3.resultVector[argument2.argument].resultEntity[argument2.argumentInd].push_back(result2[i]);
			}

			result3.noOfRows++;
		}
	}
	else
	{


		//check argument dependence
		int dependenceValue = checkIndependence(result3,argument1,argument2,both);
		if(dependenceValue==1)
		{
			if(result1.size()==0)
			{
				deleteAllRows(result3);
				return 1;
			}
			argumentTempInd = argument1.argumentInd;
			argumentTemp = argument1.argument;
		}
		if(dependenceValue==2)
		{
			if(result2.size()==0)
			{
				deleteAllRows(result3);
				return 1;
			}
			argumentTempInd = argument2.argumentInd;
			argumentTemp = argument2.argument;
		}
		//case 2: Independent from all the collumns 
		int resultVectorIndex = 0;
		int argIndex = 0;
		int tempNoOfRows = 0;
		tempNoOfRows++;

		int rowMax = result3.noOfRows;
		int count = 0;
		if(dependenceValue==-1)
		{

			for(unsigned int k = 0;k<result1.size();k++)
			{

				for(int p = 0;p<rowMax;p++)
				{
					for(unsigned int i=0;i< result3.resultVector.size();i++)
					{
						int temp = result3.resultVector[i].resultEntity.size();
						for(int j=0;j<temp;j++)
						{
							if(((i!=argument1.argument)||(i==argument1.argument&&j!=argument1.argumentInd))&&((both==0)||((i!=argument2.argument)||(i==argument2.argument&&j!=argument2.argumentInd))))
							{
								

								if(count>0)
								{
									if(result3.resultVector[i].resultEntity[j].size()>0)
									{
									int value = result3.resultVector[i].resultEntity[j][p];
									result3.resultVector[i].resultEntity[j].push_back(value);
									
									}

								}
							}
						}

					}
					result3.resultVector[argument1.argument].resultEntity[argument1.argumentInd].push_back(result1[k]);
					if(count>0)
					{
					result3.noOfRows++;
					}
					if(both==1)
					{
						result3.resultVector[argument2.argument].resultEntity[argument2.argumentInd].push_back(result2[k]);
					}
				}

				count++;


			}
		}
		else 
		{
			if(dependenceValue==1||dependenceValue==2)
			{
				//case 3: one column dependent from all the collumns 
				count = 0; //check if first iteration of insertions
				int noOfInsertions = 0;
				bool flag = false;
				for(int p = 0;p<rowMax;p++)
				{
					int value = result3.resultVector[argumentTemp].resultEntity[argumentTempInd][noOfInsertions];
					count = 0;
					for(unsigned int k = 0;k<result1.size();k++)
					{
						if((value==result1[k]&&dependenceValue==1)||((dependenceValue==2)&&(value==result2[k])))
						{
							flag = true;
							if(count>0)
							{
								for(unsigned int i=0;i< result3.resultVector.size();i++)
								{
									for(unsigned int j=0;j<result3.resultVector[i].resultEntity.size();j++)
									{
										if(result3.resultVector[i].resultEntity[j].size()!=0)
										{
											if((!((i==argument1.argument) &&( j== argument1.argumentInd)))&&(!((i==argument2.argument) && (j==argument2.argumentInd))))
											{
												int tempValue = result3.resultVector[i].resultEntity[j][noOfInsertions-1];
												result3.resultVector[i].resultEntity[j].insert(result3.resultVector[i].resultEntity[j].begin() + noOfInsertions,tempValue);
												
											}
										}
									}

								}
								if(dependenceValue==1)
								{
									int commonValue = result3.resultVector[argument1.argument].resultEntity[argument1.argumentInd][noOfInsertions-1];
									result3.resultVector[argument1.argument].resultEntity[argument1.argumentInd].insert(result3.resultVector[argument1.argument].resultEntity[argument1.argumentInd].begin() + noOfInsertions,commonValue);
									result3.noOfRows++;
									if(both==1)
									{
										result3.resultVector[argument2.argument].resultEntity[argument2.argumentInd].push_back(result2[k]);
									}
								}
								else
								{
									int commonValue = result3.resultVector[argument2.argument].resultEntity[argument2.argumentInd][noOfInsertions-1];
									result3.resultVector[argument2.argument].resultEntity[argument2.argumentInd].insert(result3.resultVector[argument2.argument].resultEntity[argument2.argumentInd].begin() + noOfInsertions,commonValue);

									result3.noOfRows++;
									result3.resultVector[argument1.argument].resultEntity[argument1.argumentInd].push_back(result1[k]);
								}
								noOfInsertions++;
							}
							else
							{
								//result3.resultVector[argument1.argumentType].resultEntity[argument1.argumentInd].push_back(result1[k]);

								if(dependenceValue==1)
								{
									if(both==1)
										result3.resultVector[argument2.argument].resultEntity[argument2.argumentInd].push_back(result2[k]);

								}
								else
								{
									result3.resultVector[argument1.argument].resultEntity[argument1.argumentInd].push_back(result1[k]);
								}
								count++;
								noOfInsertions++;
							}
						}
					}
					if(flag == false)
					{
						deleteRow(result3,noOfInsertions);
					}
					else
					{	
						flag = false;
					}
				}
			}
			else
				{
					bool flag= false;
					int noOfDeletions = 0;
				for(int p = 0;p<rowMax;p++)
				{
					int valueArg1 = result3.resultVector[argument1.argument].resultEntity[argument1.argumentInd][noOfDeletions];
					int valueArg2 = result3.resultVector[argument2.argument].resultEntity[argument2.argumentInd][noOfDeletions];
					for(unsigned int k = 0;k<result1.size();k++)
					{
						
						if((valueArg1==result1[k])&&(valueArg2==result2[k]))
						{
							flag = true;
						}
							
					}
					if(flag == false)
					{
						deleteRow(result3,noOfDeletions);
					}
					else
					{	noOfDeletions++;
						flag = false;
					}
				}
			}
		}
	}
	return 1;
}

/** Delete Row
   * 
   * @param The current result set, the row to delete from the set
   * @Deletes the row from the current set
   */
int QueryEvaluator::deleteRow(struct Result& tempResult, int rowIndex)
{
	for(unsigned int i=0;i< tempResult.resultVector.size();i++)
	{
		for(unsigned int j=0;j<tempResult.resultVector[i].resultEntity.size();j++)
		{
			if(tempResult.resultVector[i].resultEntity[j].size()>(unsigned)rowIndex)
			{
				tempResult.resultVector[i].resultEntity[j].erase(tempResult.resultVector[i].resultEntity[j].begin() + rowIndex);
				
			}

		}
	}
	tempResult.noOfRows--;
	return 1;
}

/** Delete Row
   * 
   * @param The current result set
   * @Empties the current result set
   */
int QueryEvaluator::deleteAllRows(struct Result& tempResult)
{
	for(unsigned int i=0;i< tempResult.resultVector.size();i++)
	{
		for(unsigned int j=0;j<tempResult.resultVector[i].resultEntity.size();j++)
		{

			tempResult.resultVector[i].resultEntity[j].clear();
			

		}
	}
	tempResult.noOfRows = 0;
	return 1;
}

/** check Independence
   * 
   * @param The current result set, arguments from the current query.
   * @return Returns 1 if the first argument exists in the current result set, 2 if the second argument exists in the set and 3 if both arguments exists.
   *		 Retruns -1 if they are independent;
   */
int QueryEvaluator::checkIndependence(struct Result& tempResult, struct Argument& argument1,struct Argument& argument2, int both)
{
	int returnValue = -1;

	for(unsigned int i=0;i< tempResult.resultVector.size();i++)
	{
		for(unsigned int j=0;j<tempResult.resultVector[i].resultEntity.size();j++)
		{
			if(tempResult.resultVector[argument1.argument].resultEntity[argument1.argumentInd].size()!=0)
			{
				if(returnValue==2)
				{
					returnValue = 3;
					break;
				}
				else
				{
					returnValue = 1;
				}
			}
			if(both==1)
			{
				if(tempResult.resultVector[argument2.argument].resultEntity[argument2.argumentInd].size()!=0)
				{
					if(returnValue==1)
					{
						returnValue = 3;
						break;
					}
					else
					{
						returnValue = 2;
					}
				}
			}
		}
	}
	return returnValue;

}

/** Delete Row
   * 
   * @param The current result set
   * @return Return 1 if the current result is empty and -1 if the current result set is not;
   */
int QueryEvaluator::checkEmpty(struct Result& tempResult)
{
	int empty =1;
	for(unsigned int i =0;i<tempResult.resultVector.size();i++)
	{
		for(unsigned int j =0;j<tempResult.resultVector[i].resultEntity.size();j++)
		{
			if(tempResult.resultVector[i].resultEntity[j].size()>0)
			{
				empty = 0;
				break;
			}
		}
	}
	return empty;
}

/** check Argument Necessity
   * 
   * @param The current result set , current
   * @return Return 1 if the current result is empty and -1 if the current result set is not;
   */
int QueryEvaluator::checkArgumentNecessity(struct Result& tempResult, Argument tempArg, vector<suchThatClause>& tempSuchThat)
{
	int count = 0;
	int retVal = 0;
	for(unsigned int i =0;i<tempResult.selectedType.size();i++)
	{
	if((tempResult.selectedType[i]==tempArg.argument)&&(tempResult.resultIndex[i]==tempArg.argumentInd))
	{
	return 1;
	}
	}
	for(unsigned int i =0;i<tempSuchThat.size();i++)
	{
	if(((tempSuchThat[i].arguments[0].argument==tempArg.argument)&&(tempSuchThat[i].arguments[0].argumentInd==tempArg.argumentInd))||((tempSuchThat[i].arguments[1].argument==tempArg.argument)&&(tempSuchThat[i].arguments[1].argumentInd==tempArg.argumentInd)))
	{
	count++;
	}
	}
	for(unsigned int i =0;i<tempResult.resultVector.size();i++)
	{
		for(unsigned int j =0;j<tempResult.resultVector[i].resultEntity.size();j++)
		{
			if(tempResult.resultVector[i].resultEntity[j].size()>0)
			{
				if((i==tempArg.argument)&&(j==tempArg.argumentInd))
				{
				return 1;
				}
				
			}
		}
	}
	if(count==1)
	{
	retVal = -1;
	}
	else
	{
		retVal = 1;
	}
	return retVal;
}




	